import git
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
import os
import numpy as np
from matplotlib.font_manager import FontProperties

# ------------------------
# 中文字体配置 - 直接指定字体文件路径（保留中文配置，确保英文文本正常显示）
# ------------------------
try:
    # Windows系统字体路径
    font_path = r"C:\Windows\Fonts\simhei.ttf"  # 黑体
    if not os.path.exists(font_path):
        # Linux系统字体路径
        font_path = "/usr/share/fonts/truetype/wqy/wqy-microhei.ttf"  # 文泉驿微米黑
        if not os.path.exists(font_path):
            # macOS系统字体路径
            font_path = "/System/Library/Fonts/PingFang.ttc"  # 苹方字体
            if not os.path.exists(font_path):
                raise FileNotFoundError("无法找到任何中文字体文件")

    # 创建字体属性对象
    chinese_font = FontProperties(fname=font_path)

    # 设置matplotlib使用该字体
    plt.rcParams["font.family"] = ["sans-serif"]
    plt.rcParams["font.sans-serif"] = [chinese_font.get_name()]
    plt.rcParams["axes.unicode_minus"] = False  # 正确显示负号

    print(f"成功加载中文字体: {chinese_font.get_name()}")
except Exception as e:
    print(f"警告: 无法加载中文字体，图表中文可能显示异常 - {str(e)}")
    # 保留默认配置，让matplotlib使用系统可用字体

# 配置参数
REPO_URL = "https://gitee.com/paddlepaddle/PaddleNLP.git"  # PaddleNLP仓库URL
REPO_NAME = "paddlenlp"  # 仓库简称
LOCAL_PATH = f"./{REPO_NAME}"  # 本地克隆路径


def clone_or_update_repo():
    """克隆或更新仓库，自动检测主分支"""
    if not os.path.exists(LOCAL_PATH):
        print(f"正在克隆仓库：{REPO_URL}")
        repo = git.Repo.clone_from(REPO_URL, LOCAL_PATH)
    else:
        print(f"正在更新仓库：{LOCAL_PATH}")
        repo = git.Repo(LOCAL_PATH)
        repo.remote().pull()  # 拉取最新提交
    return repo


def detect_main_branch(repo):
    """检测仓库的主分支名称（可能是main或master）"""
    if 'main' in repo.heads:
        return 'main'
    elif 'master' in repo.heads:
        return 'master'
    else:
        return repo.heads[0].name if repo.heads else None


def parse_commit_data(repo, branch_name=None):
    """解析提交历史，提取关键数据"""
    if branch_name is None:
        branch_name = detect_main_branch(repo)
        if branch_name is None:
            raise ValueError("无法检测到仓库主分支")

    print(f"使用分支：{branch_name}")
    commits = []
    try:
        for commit in repo.iter_commits(branch_name, since="2023-01-01"):
            commit_time = datetime.fromtimestamp(commit.committed_date)
            stats = commit.stats
            total_lines = stats.total.get("lines", 0) if stats else 0
            files_changed = len(stats.files) if (stats and stats.files) else 0

            author_name = commit.author.name if commit.author else "Unknown Author"

            commits.append({
                "author": author_name,
                "email": commit.author.email if commit.author else "unknown@example.com",
                "timestamp": commit_time,
                "message": commit.message.split("\n")[0] if commit.message else "No message",
                "files_changed": files_changed,
                "lines_changed": total_lines,
                "sha": commit.hexsha[:7]
            })
    except git.exc.GitCommandError:
        print("尝试不指定since参数获取所有提交...")
        for commit in repo.iter_commits(branch_name):
            commit_time = datetime.fromtimestamp(commit.committed_date)
            stats = commit.stats
            total_lines = stats.total.get("lines", 0) if stats else 0
            files_changed = len(stats.files) if (stats and stats.files) else 0

            author_name = commit.author.name if commit.author else "Unknown Author"

            commits.append({
                "author": author_name,
                "email": commit.author.email if commit.author else "unknown@example.com",
                "timestamp": commit_time,
                "message": commit.message.split("\n")[0] if commit.message else "No message",
                "files_changed": files_changed,
                "lines_changed": total_lines,
                "sha": commit.hexsha[:7]
            })

    return pd.DataFrame(commits)


def generate_visualizations(df):
    """生成项目要求的所有可视化图表"""
    os.makedirs("visuals", exist_ok=True)

    # 1. 前10位贡献者水平条形图（英文转换）
    plt.figure(figsize=(10, 6))
    top_contributors = df["author"].value_counts().head(10)
    sns.barplot(x=top_contributors.values, y=top_contributors.index, color="skyblue")
    plt.title(f"{REPO_NAME} Top 10 Contributors", fontproperties=chinese_font)
    plt.xlabel("Number of Commits", fontproperties=chinese_font)
    plt.ylabel("Contributor Name", fontproperties=chinese_font)
    plt.tight_layout()
    plt.savefig(f"visuals/{REPO_NAME}_top_contributors.png")
    plt.close()

    # 2. 过去12个月提交活动趋势（英文转换）
    if len(df) > 0:
        df["month"] = df["timestamp"].dt.to_period("M")
        monthly_commits = df["month"].value_counts().sort_index()
        recent_12 = monthly_commits.iloc[-12:] if len(monthly_commits) >= 12 else monthly_commits

        plt.figure(figsize=(12, 6))
        sns.lineplot(x=recent_12.index.astype(str), y=recent_12.values, marker="o", color="orange")
        plt.title(f"{REPO_NAME} Monthly Commit Trends (Last 12 Months)", fontproperties=chinese_font)
        plt.xlabel("Month (YYYY-MM)", fontproperties=chinese_font)
        plt.ylabel("Total Commits", fontproperties=chinese_font)
        plt.xticks(rotation=45, fontproperties=chinese_font)
        plt.tight_layout()
        plt.savefig(f"visuals/{REPO_NAME}_monthly_commits.png")
        plt.close()
    else:
        print("Warning: No commit data, skipping monthly trend chart")

    # 3. 按星期提交活动分布（英文转换）
    if len(df) > 0:
        df["day_of_week"] = df["timestamp"].dt.day_name()
        day_order = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
        commits_by_day = df["day_of_week"].value_counts().reindex(day_order, fill_value=0)

        plt.figure(figsize=(10, 6))
        sns.barplot(x=commits_by_day.index, y=commits_by_day.values, color="lightgreen")
        plt.title(f"{REPO_NAME} Commits by Day of Week", fontproperties=chinese_font)
        plt.xlabel("Day of Week", fontproperties=chinese_font)
        plt.ylabel("Total Commits", fontproperties=chinese_font)
        plt.tight_layout()
        plt.savefig(f"visuals/{REPO_NAME}_commits_by_day.png")
        plt.close()
    else:
        print("Warning: No commit data, skipping day distribution chart")

    # 4. 累计提交增长曲线（英文转换）
    if len(df) > 0:
        df_sorted = df.sort_values("timestamp")
        df_sorted["cumulative_commits"] = range(1, len(df_sorted) + 1)

        plt.figure(figsize=(12, 6))
        sns.lineplot(x=df_sorted["timestamp"], y=df_sorted["cumulative_commits"], color="red")
        plt.title(f"{REPO_NAME} Cumulative Commit Growth", fontproperties=chinese_font)
        plt.xlabel("Date", fontproperties=chinese_font)
        plt.ylabel("Cumulative Commits", fontproperties=chinese_font)
        plt.tight_layout()
        plt.savefig(f"visuals/{REPO_NAME}_cumulative_growth.png")
        plt.close()
    else:
        print("Warning: No commit data, skipping cumulative growth chart")

    # 5. 每次提交变更行数分布（英文转换）
    if len(df) > 0:
        plt.figure(figsize=(10, 6))
        sns.boxplot(y=df["lines_changed"], showfliers=False, color="purple")
        plt.title(f"{REPO_NAME} Distribution of Lines Changed per Commit", fontproperties=chinese_font)
        plt.ylabel("Lines Changed", fontproperties=chinese_font)
        plt.tight_layout()
        plt.savefig(f"visuals/{REPO_NAME}_lines_distribution.png")
        plt.close()
    else:
        print("Warning: No commit data, skipping lines distribution chart")

    # 6. 每次提交变更文件数分布（英文转换）
    if len(df) > 0:
        plt.figure(figsize=(10, 6))
        sns.boxplot(y=df["files_changed"], showfliers=False, color="green")
        plt.title(f"{REPO_NAME} Distribution of Files Changed per Commit", fontproperties=chinese_font)
        plt.ylabel("Files Changed", fontproperties=chinese_font)
        plt.tight_layout()
        plt.savefig(f"visuals/{REPO_NAME}_files_distribution.png")
        plt.close()
    else:
        print("Warning: No commit data, skipping files distribution chart")

    key_metrics = {
        "total_commits": len(df),
        "unique_authors": df["author"].nunique(),
        "first_commit_date": df["timestamp"].min().strftime("%Y-%m-%d") if len(df) > 0 else "No data",
        "last_commit_date": df["timestamp"].max().strftime("%Y-%m-%d") if len(df) > 0 else "No data",
        "avg_lines_per_commit": df["lines_changed"].mean() if len(df) > 0 else 0,
        "avg_files_per_commit": df["files_changed"].mean() if len(df) > 0 else 0
    }

    pd.DataFrame([key_metrics]).to_csv(f"{REPO_NAME}_metrics.csv", index=False)
    return {
        "metrics": key_metrics,
        "top_contributors": top_contributors if len(df) > 0 else pd.Series(),
        "monthly_commits": recent_12 if len(df) > 0 else pd.Series(),
        "commits_by_day": commits_by_day if len(df) > 0 else pd.Series(),
        "df": df
    }


def generate_markdown_report(data):
    """生成Markdown格式的仓库分析报告（英文转换图像相关说明）"""
    metrics = data["metrics"]
    top_contributors = data["top_contributors"]
    monthly_commits = data["monthly_commits"]
    commits_by_day = data["commits_by_day"]
    df = data["df"]

    with open(f"report-{REPO_NAME}.md", "w", encoding="utf-8") as f:
        f.write(f"# {REPO_NAME} Repository Analysis Report\n\n")
        f.write(f"**Analysis Time**：{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")

        # 仓库概览
        f.write("## 1. Repository Overview\n\n")
        f.write(f"- **Total Commits**：{metrics['total_commits']}\n")
        f.write(f"- **Unique Contributors**：{metrics['unique_authors']}\n")
        f.write(f"- **First Commit Date**：{metrics['first_commit_date']}\n")
        f.write(f"- **Last Commit Date**：{metrics['last_commit_date']}\n\n")

        # 贡献者分析
        f.write("## 2. Contributor Analysis\n\n")
        f.write("### Top 10 Contributors\n\n")
        if len(top_contributors) > 0:
            f.write(f"![Top 10 Contributors](visuals/{REPO_NAME}_top_contributors.png)\n\n")
            f.write(
                f"> **Note**：Contributors are sorted by the number of commits. The top contributor accounts for {top_contributors.values[0] / metrics['total_commits'] * 100:.1f}% of all commits.\n\n")
        else:
            f.write("> No commit data available for contributor analysis.\n\n")

        # 提交活动分析
        f.write("## 3. Commit Activity Analysis\n\n")

        f.write("### Monthly Commit Trends (Last 12 Months)\n\n")
        if len(monthly_commits) > 0:
            f.write(f"![Monthly Commits](visuals/{REPO_NAME}_monthly_commits.png)\n\n")
            f.write(f"> **Trend**：The peak of commits occurred in {monthly_commits.idxmax()} with {monthly_commits.max()} commits.\n\n")
        else:
            f.write("> No commit data for the last 12 months.\n\n")

        f.write("### Commits by Day of Week\n\n")
        if len(commits_by_day) > 0:
            f.write(f"![Commits by Day](visuals/{REPO_NAME}_commits_by_day.png)\n\n")
            peak_day = commits_by_day.idxmax()
            peak_ratio = commits_by_day.max() / commits_by_day.sum() * 100
            f.write(f"> **Finding**：{peak_day} has the highest number of commits, accounting for {peak_ratio:.1f}% of total commits, possibly related to weekly code merging rhythms.\n\n")
        else:
            f.write("> No commit data available for daily distribution analysis.\n\n")

        # 提交质量分析
        f.write("## 4. Commit Quality Analysis\n\n")

        f.write("### Distribution of Lines Changed per Commit\n\n")
        if len(df) > 0:
            f.write(f"![Lines Changed](visuals/{REPO_NAME}_lines_distribution.png)\n\n")
            median_lines = df["lines_changed"].median()
            q75_lines = df["lines_changed"].quantile(0.75)
            f.write(
                f"> **Statistics**：The median is {median_lines:.0f} lines, and 75% of commits change no more than {q75_lines:.0f} lines, indicating most commits are small modifications.\n\n")
        else:
            f.write("> No commit data available for line change analysis.\n\n")

        f.write("### Distribution of Files Changed per Commit\n\n")
        if len(df) > 0:
            f.write(f"![Files Changed](visuals/{REPO_NAME}_files_distribution.png)\n\n")
            f.write(
                f"> **Statistics**：90% of commits change no more than {df['files_changed'].quantile(0.9):.0f} files, which is in line with the principle of small-step commits.\n\n")
        else:
            f.write("> No commit data available for file change analysis.\n\n")

        # 仓库特性总结（保留中文说明，如需翻译可进一步调整）
        f.write("## 5. Repository Features Summary\n\n")
        f.write("PaddleNLP 是基于飞桨的自然语言处理库，具备以下核心能力：\n")
        f.write("- **多硬件支持**：兼容GPU、XPU、NPU等硬件，降低跨平台开发成本。\n")
        f.write("- **高效训练**：4D训练策略与Unified Checkpoint技术提升训练效率与存储性能。\n")
        f.write("- **丰富模型库**：支持LLaMA、Qwen、Baichuan等主流大模型，覆盖NLP全任务场景。\n")


if __name__ == "__main__":
    try:
        repo = clone_or_update_repo()
        df = parse_commit_data(repo)

        if len(df) == 0:
            print("Warning: No commit data obtained, please check the repository branch or activity time")
            exit(1)

        data = generate_visualizations(df)
        generate_markdown_report(data)
        print(f"Successfully generated {REPO_NAME} repository analysis report")
        print(f"Report file：report-{REPO_NAME}.md")
        print(f"Visualization charts are stored in the visuals/ directory")

    except Exception as e:
        print(f"Script execution failed：{str(e)}")
        import traceback

        traceback.print_exc()
        exit(1)